/** @brief File containing the declaration of the base class for graphic
 * representation.
 *
 * This file contains the declaration of the base class defining the interface
 * of the visualisation classes.
 *
 * @file RepresentationBase.hpp
 * @author Johan "Solo" Luisier
 * @date 2013/03/25
 */
#ifndef REPRESENTATIONBASE_HPP
#define REPRESENTATIONBASE_HPP

#include <QtCore/QVector>

#include <QtGui/QGraphicsScene>

class GridBase;

class QPoint;
class QPointF;

/** @brief The RepresentationBase class
 *
 * This class is not strictly speaking the visual representation, since it is
 * only derivated from QGraphicsScene. The viewing has to be performed by
 * another class. However the logic for the display is implemented in here (or
 * in the grid-specific derivated class).
 *
 * The goal is to use well-defined svg images (with known dimensions) which are
 * then put in the scene. Depending on the view widget dimensions, the images
 * are scaled so that the grid uses all the available space.
 *
 * @author Johan "Solo" Luisier
 * @date 2013/03/25
 *
 * @class RepresentationBase "RepresentationBase.hpp" "UI/RepresentationBase.hpp"
 */
class RepresentationBase : public QGraphicsScene
{
    Q_OBJECT
public:
    /** @brief Standard constructor.
     *
     * The constructor initialises the data members and connects the
     * GridBase::flipped signal to the RepresentationBase::updateCellView slot.
     *
     * @param[in] grid pointer on the grid instance.
     * @param[in] parent pointer on the parent object.
     */
    explicit RepresentationBase( GridBase* grid, QObject *parent = 0 );
    /** @brief Destructor, virtual to ensure a correct call stack.
     */
    virtual ~RepresentationBase();
    /** @brief Getter for the tile height.
     *
     * This method allows to access the tile height (in pixels, with standard
     * zoom).
     *
     * @return a const reference on the tile height.
     */
    virtual const qreal& tileHeight() const = 0;
    /** @brief Getter for the tile width.
     *
     * This method allows to access the tile width (in pixels, with standard
     * zoom).
     *
     * @return a const reference on the tile width.
     */
    virtual const qreal& tileWidth() const = 0;
    /** @brief Getter for the scene top left position.
     *
     * This method allows to access the scene top left corner (used to get the
     * correct initial view).
     *
     * @return a const reference on the position.
     */
    virtual const QPointF& topLeft() const = 0;
    /** @brief Getter for the scene bottom right position.
     *
     * This method allows to access the scene bottom right corner (used to
     * get the correct initial view).
     *
     * @return a const reference on the position.
     */
    virtual const QPointF& bottomRight() const = 0;
    
public slots:
    /** @brief The cell retrieving slot.
     *
     * This slot computes which Cell instance was clicked from the contact
     * point (in scene coordinates).
     *
     * Once the computation are done, the touchedCell() signal is sent.
     *
     * @param[in] pt contact point.
     */
    virtual void retrieveCell( const QPointF& pt ) = 0;
protected:
    /** @brief Pointer on the grid instance.
     *
     * Since the class is only a graphic representation of the grid, a `real'
     * grid is needed to perform the computations, to know the state of the
     * cells, etc.
     */
    GridBase* GridModel;
    /** @brief List of items representing the cells.
     *
     * The Cell instances are stored so that the access is made like this: the
     * Cell @f$ ( i, j ) @f$ is at the index @f$ i + j * height @f$
     */
    QVector< QGraphicsItem* > CellTiles;

protected slots:
    /** @brief The cell toggle slot.
     *
     * This slot is used to toggle the visual state of a cell reprensentation.
     * For a given point, the corresponding tile is flipped, meaning an
     * unvisible tile will become visible and vice-versa.
     *
     * @param[in] coord coordinates of the tile.
     */
    void updateCellView( const QPoint& coord );

private:
    /** @brief Method creating the tiles for cell visualisation.
     *
     * This method creates the visual representation by creating a
     * QGraphicsItem for each cell.
     */
    virtual void setupTiles() = 0;
signals:
    /** @brief The touched Cell signal.
     *
     * This signal is sent once the Cell instance which on which the user
     * clicked has been determined. The sent parameter is the coordinates in
     * the grid.
     *
     * @param[out] pt coordinates of the Cell instance in the grid.
     */
    void touchedCell( const QPoint& pt );
};

#endif // REPRESENTATIONBASE_HPP
